package org.cnc.core;

import java.util.ArrayList;

import org.cnc.core.DetailModel.ModelState;
import org.cnc.machine.CutterPosition;

public class MachineControl 
{
	public enum Command 
	{ 
		RIGHT,
		LEFT,	 
		DOWN,
		UP, 
		FORWARD,
		BACK,	
		RETURN,
		WAIT,
		STOP;
	}	
	
	public enum MachineMode
	{
		AUTOMATIC, MANUAL
	}
	
	private Command nextStep = Command.STOP;
	private boolean keyPressed = false;
	private int delayTime;
	
	public MachineControl() 
	{
		machine_program = new ArrayList<MachineControl.Command>();
		cutterPos = new CutterPosition();
	}
	
	public int getDelayTime()
	{
		return delayTime;
	}
	
	public void setDelayTime( int delay )
	{
		this.delayTime = delay;
	}
	
	public MachineMode getMode()
	{
		return mode;
	}

	public Command getNextStep()
	{
		if ( mode == MachineMode.AUTOMATIC )
		{
			nextStep = machine_program.remove(0); 
			return nextStep;
		}
		else
		{
			while ( !keyPressed && mode != MachineMode.AUTOMATIC )
			{
				try {
					Thread.sleep( 100 );
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			
			nextStep = machine_program.remove(0);
			keyPressed = false;
			return nextStep;
		}
	}
	
	public CutterPosition getInitCutterPosition()
	{
		return cutterPos;
	}
	
	public void generateCommands(DetailModel model)
	{
		machine_program.clear();
		
		boolean found_cutter = false;
		int first_x = 0, first_y = model.getModelSize() - 1, first_z = 0;
		for ( first_z = 0; first_z < model.getModelSize() && !found_cutter; ++first_z )
			for ( first_y = model.getModelSize() - 1; first_y >= 0 && !found_cutter; --first_y )
				for ( first_x = 0; first_x < model.getModelSize() && !found_cutter; first_x++ )
					if (model.detailModel[first_x][first_y][first_z] == ModelState.CUTTER)
						found_cutter = true;						

		if (!found_cutter)
		{
			machine_program.add(Command.STOP);
			return;
		}
		
		first_x--;
		first_y++;
		first_z--;		
		
		cutterPos.x( first_x - 1 );
		cutterPos.y( first_y + 1 );
		cutterPos.z( first_z );
		
		System.out.println("MachineControl: x:"+ (first_x-1) +" y:" + (first_y+1) + " z: " + first_z);
		
		int x_width = 0, y_width = 0, z_width = 0;
		for ( int x = first_x ; x < model.getModelSize(); ++x )
			if (model.detailModel[x][first_y][first_z] == ModelState.CUTTER)
				++x_width;
		
		for ( int y = first_y ; y >= 0; --y )
			if (model.detailModel[first_x][y][first_z] == ModelState.CUTTER)
				++y_width;
		
		for ( int z = first_z ; z < model.getModelSize(); ++z )
			if (model.detailModel[first_x][first_y][z] == ModelState.CUTTER)
				++z_width;
		
		for ( int y = 0 ; y < y_width; ++y )
		{
			machine_program.add(Command.DOWN);
			
			for ( int z = 0 ; z < z_width; ++z )
			{
				for ( int x = 0 ; x < x_width; ++x )		
				{
					machine_program.add(Command.RIGHT);
				}
				
				machine_program.add(Command.RETURN);
				
				if (z< z_width - 1)
				{
					if (y%2 == 0)
						machine_program.add(Command.BACK);
					else
						machine_program.add(Command.FORWARD);				
				}
			}
		}	
		
		machine_program.add(Command.STOP);
	}

	
	public void setMode(MachineMode m) {
		this.mode = m;
	}

	public void makeStep() {
		keyPressed = true;
	}
	
	public void makeStep( Command cmd ) {
		machine_program.add(0, cmd);
		makeStep();
	}

	// fields
	private	ArrayList<Command> machine_program;
	private CutterPosition cutterPos;
	private MachineMode mode = MachineMode.AUTOMATIC;
}
